<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=625289
-->
<head>
  <meta charset="utf-8">
  <title>Test for Bug 625289</title>
  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
  <style>
  :root,
  #e1, #e2 > div,
  #b1::before, #b2 > div::before,
  #a1::after, #a2 > div::after {
    margin-left: 0;
  }
  :root.t,
  #e1.t, #e2.t > div,
  #b1.t::before, #b2.t > div::before,
  #a1.t::after, #a2.t > div::after {
    transition: margin-left linear 1s;
  }
  #b1::before, #b2 > div::before,
  #a1::after, #a2 > div::after {
    content: "x";
    display: block;
  }
  :root.m,
  #e1.m, #e2.m > div,
  #b1.m::before, #b2.m > div::before,
  #a1.m::after, #a2.m > div::after {
    margin-left: 100px;
  }
  .o { overflow: hidden }
  .n { display: none }

  #fline { color: blue; font-size: 20px; width: 800px; }
  #fline::first-line { color: yellow }
  #fline.narrow { width: 50px }
  #fline i { transition: color linear 1s }

  #flexboxtest #flex { display: flex; flex-direction: column }
  #flexboxtest #flextransition { color: blue; transition: color 5s linear }

  #flexboxtest #flexkid[newstyle] { resize: both }
  #flexboxtest #flextransition[newstyle] { color: yellow }
  </style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=625289">Mozilla Bug 625289</a>
<div id="container"></div>
<div id="fline">
  This text has an <i>i element</i> in it.
</div>
<div id="flexboxtest">
  <div id="flex">
    hello
    <span id="flexkid">this appears</span>
    hello
    <div id="flextransition">color transition</div>
  </div>
</div>
<pre id="test">
<script>
"use strict";

function advance_clock(milliseconds) {
  SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(milliseconds);
}

var container = document.getElementById("container");

function make_elements(idName, child) {
  var e = document.createElement("div");
  e.setAttribute("id", idName);
  if (child) {
    e.appendChild(document.createElement("div"));
  }
  container.appendChild(e);
  return e;
}

function assert_margin_at_quarter(element, pseudo, passes)
{
  var desc;
  var useParent = false;
  if (element == document.documentElement) {
    desc = "root element";
  } else if (element.id) {
    desc = "element " + element.id;
  } else {
    desc = "child of element " + element.parentNode.id;
    useParent = true;
  }
  var classes = (useParent ? element.parentNode : element).getAttribute("class");
  if (classes) {
    desc += " (classes: " + classes + ")";
  }
  if (pseudo) {
    desc += " " + pseudo + " pseudo-element";
  }
  (passes ? is : todo_is)(getComputedStyle(element, pseudo).marginLeft, "25px",
                          "margin of " + desc);
}

function do_test(test)
{
  var expected_props = [ "element", "test_child", "pseudo", "passes",
                         "dynamic_change_transition", "start_from_none" ];
  for (var propidx in expected_props) {
    if (! expected_props[propidx] in test) {
      ok(false, "expected " + expected_props[propidx] + " on test object");
    }
  }

  var e;
  if (typeof(test.element) == "string") {
    e = make_elements(test.element, test.test_child);
  } else {
    if (test.test_child) {
      ok(false, "test_child unexpected");
    }
    e = test.element;
  }

  var target = test.test_child ? e.firstChild : e;

  if (!test.dynamic_change_transition) {
    e.classList.add("t");
  }
  if (test.start_from_none) {
    e.classList.add("n");
  }

  advance_clock(100);
  e.classList.add("m");
  e.classList.add("o");
  if (test.dynamic_change_transition) {
    e.classList.add("t");
  }
  if (test.start_from_none) {
    e.classList.remove("n");
  }
  advance_clock(0);
  advance_clock(250);
  assert_margin_at_quarter(target, test.pseudo, test.passes);
  if (typeof(test.element) == "string") {
    e.remove();
  } else {
    target.style.transition = "";
    target.removeAttribute("class");
  }
}

advance_clock(0);

var tests = [
  { element:"e1", test_child:false, pseudo:"", passes:true,
    dynamic_change_transition:false, start_from_none:false },
  { element:"e2", test_child:true, pseudo:"", passes:true,
    dynamic_change_transition:false, start_from_none:false },
  { element:"b1", test_child:false, pseudo:"::before", passes:true,
    dynamic_change_transition:false, start_from_none:false },
  { element:"b2", test_child:true, pseudo:"::before", passes:true,
    dynamic_change_transition:false, start_from_none:false },
  { element:"a1", test_child:false, pseudo:"::after", passes:true,
    dynamic_change_transition:false, start_from_none:false },
  { element:"a2", test_child:true, pseudo:"::after", passes:true,
    dynamic_change_transition:false, start_from_none:false },
  { element:document.documentElement, test_child:false, pseudo:"", passes:true,
    dynamic_change_transition:false, start_from_none:false },
  // Recheck with a dynamic change in transition
  { element:"e1", test_child:false, pseudo:"", passes:true,
    dynamic_change_transition:true, start_from_none:false },
  { element:"e2", test_child:true, pseudo:"", passes:true,
    dynamic_change_transition:true, start_from_none:false },
  { element:"b1", test_child:false, pseudo:"::before", passes:true,
    dynamic_change_transition:true, start_from_none:false },
  { element:"b2", test_child:true, pseudo:"::before", passes:true,
    dynamic_change_transition:true, start_from_none:false },
  { element:"a1", test_child:false, pseudo:"::after", passes:true,
    dynamic_change_transition:true, start_from_none:false },
  { element:"a2", test_child:true, pseudo:"::after", passes:true,
    dynamic_change_transition:true, start_from_none:false },
  { element:document.documentElement, test_child:false, pseudo:"", passes:true,
    dynamic_change_transition:true, start_from_none:false },
  // Recheck starting from display:none.  Note that these tests all fail,
  // although we could get *some* of them to pass by calling
  // RestyleManager::TryInitiatingTransition from
  // ElementRestyler::RestyleUndisplayedChildren.
  { element:"e1", test_child:false, pseudo:"", passes:false,
    dynamic_change_transition:false, start_from_none:true },
  { element:"e2", test_child:true, pseudo:"", passes:false,
    dynamic_change_transition:false, start_from_none:true },
  { element:"b1", test_child:false, pseudo:"::before", passes:false,
    dynamic_change_transition:false, start_from_none:true },
  { element:"b2", test_child:true, pseudo:"::before", passes:false,
    dynamic_change_transition:false, start_from_none:true },
  { element:"a1", test_child:false, pseudo:"::after", passes:false,
    dynamic_change_transition:false, start_from_none:true },
  { element:"a2", test_child:true, pseudo:"::after", passes:false,
    dynamic_change_transition:false, start_from_none:true },
  { element:document.documentElement, test_child:false, pseudo:"", passes:false,
    dynamic_change_transition:false, start_from_none:true },
  // Recheck with a dynamic change in transition and starting from display:none
  { element:"e1", test_child:false, pseudo:"", passes:false,
    dynamic_change_transition:true, start_from_none:true },
  { element:"e2", test_child:true, pseudo:"", passes:false,
    dynamic_change_transition:true, start_from_none:true },
  { element:"b1", test_child:false, pseudo:"::before", passes:false,
    dynamic_change_transition:true, start_from_none:true },
  { element:"b2", test_child:true, pseudo:"::before", passes:false,
    dynamic_change_transition:true, start_from_none:true },
  { element:"a1", test_child:false, pseudo:"::after", passes:false,
    dynamic_change_transition:true, start_from_none:true },
  { element:"a2", test_child:true, pseudo:"::after", passes:false,
    dynamic_change_transition:true, start_from_none:true },
  { element:document.documentElement, test_child:false, pseudo:"", passes:false,
    dynamic_change_transition:true, start_from_none:true },
];

for (var testidx in tests) {
  do_test(tests[testidx]);
}

var fline = document.getElementById("fline");
var fline_i_cs = getComputedStyle(fline.firstElementChild, "");
// Note that the color in the ::first-line is never used in the test
// since we avoid reporting ::first-line data in getComputedStyle.
// However, if we were to start a transition (incorrectly), that would
// show up in getComputedStyle.
var COLOR_IN_LATER_LINES = "rgb(0, 0, 255)";

function do_firstline_test(test) {
  if (test.widening) {
    fline.classList.add("narrow");
    is (fline_i_cs.color, COLOR_IN_LATER_LINES, "initial color");
  } else {
    is (fline_i_cs.color, COLOR_IN_LATER_LINES, "initial color");
  }

  if (test.widening) {
    fline.classList.remove("narrow");
  } else {
    fline.classList.add("narrow");
  }

  if (test.set_overflow) {
    fline.classList.add("o");
  }

  advance_clock(100);

  if (test.widening) {
    is (fline_i_cs.color, COLOR_IN_LATER_LINES,
        "::first-line changes don't trigger transitions");
  } else {
    is (fline_i_cs.color, COLOR_IN_LATER_LINES,
        "::first-line changes don't trigger transitions");
  }

  fline.removeAttribute("class");
}

var firstline_tests = [
  { widening: true, set_overflow: false },
  { widening: false, set_overflow: false },
  { widening: true, set_overflow: true },
  { widening: false, set_overflow: true },
];

for (var firstline_test_idx in firstline_tests) {
  do_firstline_test(firstline_tests[firstline_test_idx]);
}

function do_flexbox_reframe_test()
{
  var flextransition = document.getElementById("flextransition");
  var cs = getComputedStyle(flextransition, "");
  cs.backgroundColor;
  flextransition.setAttribute("newstyle", "");
  document.getElementById("flexkid").setAttribute("newstyle", "");
  is(cs.color, "rgb(0, 0, 255)",
     "color at start of wrapped flexbox transition");
  advance_clock(1000);
  is(cs.color, "rgb(51, 51, 204)",
     "color one second in to wrapped flexbox transition");
}

do_flexbox_reframe_test();

SpecialPowers.DOMWindowUtils.restoreNormalRefresh();

</script>
</pre>
</body>
</html>
